;=======
;常量
;=======
app_lba_start equ 1
FDC_DOR         equ 0x3F2  ; 数字输出寄存器
FDC_MSR         equ 0x3F4  ; 主状态寄存器
FDC_DATA        equ 0x3F5  ; 数据寄存器

SECTION mbr align=16 vstart=0x7c00
    ;设置段地址
    mov ax,0
    mov ss,ax
    mov sp,ax
    mov ax,0xb800
    mov es,ax

    mov ax,[cs:phy_base] ; 程序加载处的物理地址
    mov dx,[cs:phy_base+0x02] ; 4字节
    mov bx,16  
    div bx         ; 取段地址
    mov ds,ax
   
    ;读磁盘
    xor di,di
    mov si,app_lba_start
    xor bx,bx
    call read_floppy_disk_0

    mov cx,24
    mov di,0x0000
    @ll:
        mov al,[bx]
        mov [es:di],al
        inc di
        mov byte [es:di],0x07
        inc di
        loop @ll

    jmp $

;================
; 读1个扇区的软盘数据到内存
; di、si - 扇区 LBA 值，使用di的低12位和si的全部16位，共计28位
; ds:bx - 写入内存逻辑地址
;================
read_floppy_disk_0:
    push ax
    push bx
    push cx
    push dx

    ; 0x7c29
    mov byte [cs:@3],0
    mov byte [cs:@3+1],0
    mov byte [cs:@3+2],2

    ; === 1. 复位软盘控制器 ===
    mov dx, FDC_DOR     ; DOR 地址
    mov al, 0x00
    out dx, al
    mov cx, 1000
    .delay_loop:
        loop .delay_loop  
    mov al, 0x1C      ; 启用 FDC，选择驱动器 0 并打开马达  00011100
    out dx, al        ; 写入到 DOR
    call wait_fdc_ready        ; 等待马达启动

    ; 设置数据速率
    mov dx, 0x3F7
    mov al, 0x00          ; 500 kbps
    out dx, al
    call wait_fdc_ready

    ; 寻道
    mov cl,[cs:@3]   ; 柱面号
    mov ch,[cs:@3+1]   ; 磁头号   
    call floppy_seek

    mov dx, FDC_DATA  ; FDC 数据端口
    mov al, 0xE6      ; 读数据命令
    out dx, al

    mov al,ch   ; 磁头号   
    shl al,2
    out dx, al
    
    mov al, cl
    out dx, al

    mov al, ch
    out dx, al

    mov al,[cs:@3+2]   ; 扇区号
    out dx, al

    mov al, 2     ; 扇区大小
    out dx, al

    mov al, 18          ; 每磁道的扇区数
    out dx, al

    mov al, 0x1B      ; 间隙长度
    out dx, al

    mov al, 0xFF     ; 数据长度
    out dx, al

    call wait_fdc_ready

    mov cx,512 ; 共读取 512 byte   0x7c77
    mov dx, FDC_DATA          ; FDC 数据端口
    .readw:
        in al,dx
        mov [bx],al
        inc bx
        loop .readw
    
    pop dx
    pop cx
    pop bx
    pop ax

    ret

;================
; 磁盘寻道
; track = cl
; head = ch
;================
floppy_seek:
    push ax
    push dx
    mov dx, FDC_DATA          ; FDC 数据端口
    mov al, 0x0F      ; 寻道命令
    out dx, al

    shl ch, 2
    mov al, ch
    out dx, al

    mov al, cl
    out dx, al
    call wait_fdc_ready
    pop dx
    pop ax
    ret

wait_fdc_ready:
    push ax
    push dx
    mov dx, FDC_MSR          ; FDC 主状态寄存器
.wait_loop:
    in al, dx              ; 读取状态寄存器
    and al, 0x80          ; 检查位 7 (BUSY) 
    cmp al, 0x80          ; 检查位 7 (BUSY) 
    jnz .wait_loop         ; 如果 FDC 忙碌，继续等待
    pop dx
    pop ax
    ret

@3: db 0,0,0    ; 用于存储 柱面、磁头、扇区

phy_base: dd 0x10000   ;程序被加载处的物理地址

times 510-($-$$) db 0
db 0x55, 0xaa